/**
 * 实现图片的上传
 */
package com.sfac.javaSpringBoot.modules.common.service.impl;

import com.sfac.javaSpringBoot.config.ResourceProperties;
import com.sfac.javaSpringBoot.modules.common.entity.ImageType;
import com.sfac.javaSpringBoot.modules.common.entity.Result;
import com.sfac.javaSpringBoot.modules.common.service.ImageService;
import com.sfac.javaSpringBoot.util.FileUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

/**
 *校验：文件是否为空、文件类型、文件尺寸大小
 * 检查目标文件夹是否存在，如果不存在则创建对应的文件夹
 * 文件重命名
 * 可选：变更图片像素
 * 将图片写到目标地址
 * 返回result,包装图片的相对路径地址
 */
@Service
public class ImageServiceImpl implements ImageService {

    @Autowired
    private ResourceProperties resourceProperties;
    @Value("${artifactId}")
    private String artifactId;

    @Override
    public Result<String> uploadImage(MultipartFile file, String imageTypeName) {
        // 校验：文件是否为空、文件类型、文件尺寸大小
        //判断文件是否为空
        /**
         * 测试图片上传，断点位置2
         */
        if (file.isEmpty()){
            return new Result<>(Result.ResultCode.FAILED.code,
                    "File is empty.");
        }
        //判断文件是否为image
        if (!FileUtil.isImage(file)) {
            return new Result<>(Result.ResultCode.FAILED.code,
                    "Please upload image file.");
        }
        //找到imageType枚举，在/modules/common/entity/ImageType中，有三种类型，小图、中图、大图
        ImageType imageType = ImageType.getImageTypeByName(imageTypeName);
        if (imageType == null) {
            return new Result<>(Result.ResultCode.FAILED.code,
                    "Image type error.");
        }
        //看文件的尺寸是否符合要求
        if ((file.getSize() / 1024) > imageType.size) {//文件的单位从b转换为kb
            return new Result<>(Result.ResultCode.FAILED.code,
                    "Image size exceed range.");
        }

        // 检查目标文件夹是否存在，如果不存在则创建对应的文件夹
        String systemName = System.getProperty("os.name");//查看本机系统，是"Windows 10"
        //localPath本地的文件夹路径d:/upload/
        String localPath = systemName.toLowerCase().startsWith("win") ?
                resourceProperties.getWindowLocation() :
                resourceProperties.getLinuxLocation();
        //目标文件夹   "D:/upload/java_spring_boot_18/big-image"
        String destFolderPath = String.format("%s%s/%s", localPath, artifactId, imageTypeName);
        File destFolder = new File(destFolderPath);
        if (!destFolder.exists()) {
            destFolder.mkdirs();
        }

        // 文件重命名
        String originalFilename = file.getOriginalFilename();
        String[] temp = originalFilename.split("\\.");//split切割，通过“.”来切割，为了得到后缀名,"\\."中的两个"\\"是转义字符
        String suff = temp[temp.length - 1];
        String fileName = String.format("%s.%s",//前面是文件名，后面是后缀名
                System.currentTimeMillis(), suff);//currentTimeMillis()是当前的时间戳+图片后缀名

        try {
            // 将图片写到目标地址
            String destFilePath = String.format("%s/%s", destFolderPath, fileName);//"%s/%s"=目标文件夹路径+目标文件名
            File destFile = new File(destFilePath);
            file.transferTo(destFile);

            // 可选：变更图片像素
            /**
             * FileUtil中的changeImageSize方法，第一个destFilePath代表原文件路径，第二个destFilePath代表目标文件路径
             * imageType.width，imageType.length代表的是变更后的图片像素
             */
            FileUtil.changeImageSize(destFilePath, destFilePath, imageType.width, imageType.length);

            // 返回 result，包装图片的相对路径地址（relatedPath）
            /**
             * %s%s/%s/%s = 相对路径地址（/upload/)+(artifactId)目标文件夹路径+图片类型的名字+图片名字
             * (artifactId)目标文件夹路径在application中设置（第38行）
             */
            //   relatedPath = upload/java_spring_boot_18/big-image
            String relatedPath = String.format("%s%s/%s/%s",
                    resourceProperties.getPath(), artifactId, imageTypeName, fileName);
            return new Result<>(Result.ResultCode.SUCCESS.code,
                    "Upload image success.", relatedPath);//上传图片成功
        } catch (IOException e) {
            e.printStackTrace();
            return new Result<>(Result.ResultCode.FAILED.code,
                    "Upload image error.");//上传图片失败
        }
    }
}
